package it.uniroma2.art.coda.imdb;

import it.uniroma2.art.coda.core.CODACore;
import it.uniroma2.art.coda.exception.CODAComponentNotSetException;
import it.uniroma2.art.coda.exception.FelixInitializationException;
import it.uniroma2.art.coda.exception.PRParserException;
import it.uniroma2.art.coda.interfaces.IdentityResolverInterface;
import it.uniroma2.art.coda.interfaces.ProjectionRulesDeciderInterface;
import it.uniroma2.art.coda.interfaces.ResourcesSmartSuggesterInterface;
import it.uniroma2.art.coda.interfaces.TriplesSmartSuggesterInterface;
import it.uniroma2.art.coda.projectionrule.PlaceholderStruct;
import it.uniroma2.art.coda.projectionrule.ProjectionRule;
import it.uniroma2.art.coda.structures.ARTTriple;
import it.uniroma2.art.coda.structures.BindLabelToExistingARTURIResource;
import it.uniroma2.art.coda.structures.CodaFinalSuggestions;
import it.uniroma2.art.coda.structures.PreviousDecisionSingleElement;
import it.uniroma2.art.coda.structures.PreviousDecisions;
import it.uniroma2.art.coda.structures.SelectedProjectionRules;
import it.uniroma2.art.coda.structures.ResourcesSmartSuggesterStruct;
import it.uniroma2.art.coda.structures.SuggOntologyCoda;
import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelCreationException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.exceptions.QueryEvaluationException;
import it.uniroma2.art.owlart.exceptions.UnsupportedQueryLanguageException;
import it.uniroma2.art.owlart.exceptions.UnsupportedRDFFormatException;
import it.uniroma2.art.owlart.io.RDFFormat;
import it.uniroma2.art.owlart.model.ARTLiteral;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTStatement;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.NodeFilters;
import it.uniroma2.art.owlart.models.OWLArtModelFactory;
import it.uniroma2.art.owlart.models.OWLModel;
import it.uniroma2.art.owlart.models.RDFModel;
import it.uniroma2.art.owlart.models.TransactionBasedModel;
import it.uniroma2.art.owlart.models.UnloadableModelConfigurationException;
import it.uniroma2.art.owlart.models.UnsupportedModelConfigurationException;
import it.uniroma2.art.owlart.models.conf.BadConfigurationException;
import it.uniroma2.art.owlart.navigation.ARTStatementIterator;
import it.uniroma2.art.owlart.navigation.ARTURIResourceIterator;
import it.uniroma2.art.owlart.query.MalformedQueryException;
import it.uniroma2.art.owlart.sesame2impl.factory.ARTModelFactorySesame2Impl;
import it.uniroma2.art.owlart.sesame2impl.models.conf.Sesame2ModelConfiguration;
import it.uniroma2.art.owlart.sesame2impl.models.conf.Sesame2PersistentInMemoryModelConfiguration;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.uima.UIMAFramework;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.jcas.JCas;
import org.apache.uima.pear.tools.PackageBrowser;
import org.apache.uima.pear.tools.PackageInstaller;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CompleteCODATest {

	private static Logger logger = LoggerFactory.getLogger(CompleteCODATest.class);

	// private String baseUri = "http://art.uniroma2.it/imdb";
	private String baseUri = "http://my.ontology";
	// private String importedUri = "http://art.uniroma2.it/imdb";
	private String importedUri = "http://my.ontology/imnported";
	private static String rdfInputFilePath;
	// private String rdfInputFilePath = "E:/CODATest/imdb/IMDB.owl";
	// private String rdfInputFilePath = "IMDB.owl";
	// private String rdfInputFilePath = "E:/CODATest/imdb/IMDBOutPutComplete.owl";
	// private String rdfInputFilePath = "E:/CODATest/imdb/IMDBOutPutComplete_test.owl";
	// private String rdfOutputFilePath = "E:/CODATest/imdb/IMDBOutPutComplete_test7.owl";
	private static String rdfOutputFilePath;
	private static String rdfOutputFileBaseName = "OutputComplete_demo_";

	private String imdbListFilePath = "imdbList.txt";

	private static boolean useAutocommit;

	private static boolean useResoner;

	private static boolean recursiveOntologyImport;

	private static int stopCont; // when to stop, the number is include (annotate)

	private static int whenToSave; // the number of annotatated file after which the ontology is saved to a
	// file

	// private int numberOfProcess = 2;

	private Map<String, ProjectionRulesDeciderInterface> prdMap = new HashMap<String, ProjectionRulesDeciderInterface>();
	private Map<String, IdentityResolverInterface> irMap = new HashMap<String, IdentityResolverInterface>();
	private Map<String, ResourcesSmartSuggesterInterface> rssMap = new HashMap<String, ResourcesSmartSuggesterInterface>();
	private Map<String, TriplesSmartSuggesterInterface> tssMap = new HashMap<String, TriplesSmartSuggesterInterface>();
	

	// private String dirComponentsPath = "E:/CODATest/components";
	private String dirComponentsPath = "components";

	// private String repositoryDirPath = "E:/CODATest/imdb/repDir";
	private String repositoryDirPath = "repDir";
	// private String repositoryDirPath =
	// "C:/Users/Andrea/AppData/Roaming/Mozilla/Firefox/Profiles/uhf5xedq.testST/SemanticTurkeyData/projects/CODATest/store";

	private PreviousDecisions prevDec = new PreviousDecisions();

	// private String oSGiDirPath = "E:/CODATest/OSGiCache";
	private String oSGiDirPath = "OSGiCache";

	private String inputFiles = "inputFiles";

	// private String prFilePath = "E:/CODATest/imdb/IMDB.pr";
	// private String prFilePath = "IMDB.pr";
	private static String prFilePath;

	private String[] uriToAddArray = {};

	private boolean checkuriToAdd = false;

	public static void main(String args[]) {

		if (args.length < 7) {
			System.out
					.println("Usage: java CompleteCODATest ontologyFile PEARLFile useRecursiveOntologyImport" +
							" numSiteToAnn numAnnWhenToSave useAutocommit useResoner");
			System.exit(1);
		}

		rdfInputFilePath = args[0];
		prFilePath = args[1];
		recursiveOntologyImport = (args[2].compareTo("t") == 0) ? true : false;
		stopCont = Integer.parseInt(args[3]);
		whenToSave = Integer.parseInt(args[4]);
		useAutocommit = (args[5].compareTo("t") == 0) ? true : false;
		useResoner = (args[6].compareTo("t") == 0) ? true : false;

		String prFilePathLocal = (new File(prFilePath)).getName();
		
		rdfOutputFilePath = rdfOutputFileBaseName + prFilePathLocal +"_"+args[2] + args[5] + args[6] + ".owl";

		logger.info("rdfInputFilePath = " + rdfInputFilePath);
		logger.info("prFilePath = " + prFilePath);
		logger.info("recursiveOntologyImport = " + recursiveOntologyImport);
		logger.info("stopCont = " + stopCont);
		logger.info("useAutocommit = " + useAutocommit);
		logger.info("useResoner = " + useResoner);

		CompleteCODATest completeExec = new CompleteCODATest();

		OWLModel owlModel = null;
		CODACore codaCore = null;
		long start = System.currentTimeMillis();
		long numAddedTriples = 0;

		try {
			// List<ImdbDBStruct> imdbDBStructList = completeExec.exexuteQuery();
			// List<ImdbDBStruct> imdbDBStructList = completeExec.parseImdbFile();

			List<String> fileHtmlList = completeExec.getfileHtmlList();

			// String pearPathString = "E:\\CODATest\\imdb.pear";
			String pearPathString = "imdb.pear";
			// String installedPearString = "E:\\CODATest\\installedPear";
			String installedPearString = "installedPear";

			// String oSGiDirPath = "E:/CODATest/OSGiCache";
			String descrPathString = completeExec.installPear(pearPathString, installedPearString);

			// Create an OWLModel and the triple Store.
			owlModel = completeExec.initializeOWLModel();

			// Initialize CODACORE
			codaCore = completeExec.initializeCODACore(null, owlModel);

			// set the 3 maps containing all the three different type of modules
			completeExec.setMap(codaCore);

			// choose the 3 selected modules
			completeExec.setSelectedModule(codaCore);

			// completeExec.setNumOfPrevDec(-1);
			completeExec.setNumOfPrevDec(-1);

			// Printing the projection rule
			if (logger.isDebugEnabled())
				codaCore.getProjRuleModel().printModel();
			int cont = 0;
			int startCont = 1;
			// int stopCont = 1000000; // when to stop, the number is include (annotate)

			int numbOfWebPageAnnForDBEntry;
			// logger.info("number of result = " + imdbDBStructList.size());
			logger.info("number of result = " + fileHtmlList.size());

			// prepare the thread array according to how many thread the programm will have

			// create the Analysis Engine and the JCas
			System.out.println("descrPathString = " + descrPathString);
			AnalysisEngine ae = completeExec.createAnalysisEngine(descrPathString);
			JCas jcas = completeExec.createJCas(ae);

			// for (ImdbDBStruct imdbDBStruct : imdbDBStructList) {
			for (String fileHtmlPath : fileHtmlList) {

				completeExec.clearAllPrevDec();
				++cont;
				if (cont < startCont)
					continue;

				if (cont % whenToSave == 0) {
					// Save the ontology
					completeExec.saveRDF(owlModel);
				}

				if (cont > stopCont)
					break;

				String textToBeAnnotatate = completeExec.getTextToBeAnnotatedFromFile(fileHtmlPath);

				// use the UIMA AAE to annotate the text
				logger.info(cont + " annotating file = " + fileHtmlPath);
				// logger.info(cont + " textToBeAnnotatate = " + textToBeAnnotatate); // da cancellare
				// JCas annotCas = completeExec.analyzeText(descrPathString, textToBeAnnotatate);
				completeExec.analyzeNewText(ae, jcas, textToBeAnnotatate);

				// set the jcas in CODA
				codaCore.setJCas(jcas);

				// process all the UIMA annotation
				long numAddedTriplesTemp = completeExec.processUIMAAnnotation(codaCore, owlModel);
				numAddedTriples += numAddedTriplesTemp;

				/*
				 * // old versione with internet connection completeExec.clearAllPrevDec();
				 * 
				 * numbOfWebPageAnnForDBEntry = 0; ++cont;
				 * 
				 * if (cont < startCont) continue;
				 * 
				 * if (cont % 10 == 0) { // Save the ontology completeExec.saveRDF(owlModel); } if (cont >
				 * stopCont) break;
				 * 
				 * // String sitoIMDBFromDB = imdbDBStruct.getSitoIMDBFromDB(); // int voto =
				 * imdbDBStruct.getVoto(); // int voto = 2; // String varie = imdbDBStruct.getVarie(); // int
				 * numDVD = imdbDBStruct.getNumDVD();
				 * 
				 * // if (sitoIMDBFromDB == null || sitoIMDBFromDB.compareTo("") == 0) // continue;
				 * 
				 * while (numbOfWebPageAnnForDBEntry < 2) { String sitoIMDB; ++numbOfWebPageAnnForDBEntry; if
				 * (numbOfWebPageAnnForDBEntry == 2) sitoIMDB = sitoIMDBFromDB + "fullcredits#cast"; else
				 * sitoIMDB = sitoIMDBFromDB;
				 * 
				 * String textToBeAnnotatate = ""; int numTry = 0; while (textToBeAnnotatate.compareTo("") ==
				 * 0 && numTry < 4) { textToBeAnnotatate = completeExec.getTextToBeAnnotated(sitoIMDB);
				 * ++numTry; } if (textToBeAnnotatate.compareTo("") == 0) { logger.info(cont +
				 * " problem with " + sitoIMDB); continue; // it was not possible to retrieve the page, even
				 * after 4 attempt } // use the UIMA AAE to annotate the text logger.info(cont +
				 * " annotating file = " + sitoIMDB); // JCas annotCas =
				 * completeExec.analyzeText(descrPathString, textToBeAnnotatate);
				 * completeExec.analyzeNewText(ae, jcas, textToBeAnnotatate);
				 * 
				 * // set the jcas in CODA codaCore.setJCas(jcas);
				 * 
				 * // process all the UIMA annotation completeExec.processUIMAAnnotation(codaCore, owlModel);
				 * 
				 * // if (numbOfWebPageAnnForDBEntry == 2) // completeExec.addOtherInfoToRDF(owlModel,
				 * sitoIMDBFromDB, voto, varie, numDVD); }
				 */
			}

			// Save the ontology
			completeExec.saveRDF(owlModel);

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (FelixInitializationException e) {
			e.printStackTrace();
		} catch (PRParserException e) {
			e.printStackTrace();
		} catch (ModelUpdateException e) {
			e.printStackTrace();
		} catch (ModelAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedRDFFormatException e) {
			e.printStackTrace();
		} catch (ModelCreationException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedModelConfigurationException e) {
			e.printStackTrace();
		} catch (UnloadableModelConfigurationException e) {
			e.printStackTrace();
		} catch (AnalysisEngineProcessException e) {
			e.printStackTrace();
		} catch (ResourceInitializationException e) {
			e.printStackTrace();
		} catch (InvalidXMLException e) {
			e.printStackTrace();
		} catch (UnsupportedQueryLanguageException e) {
			e.printStackTrace();
		} catch (MalformedQueryException e) {
			e.printStackTrace();
		} catch (QueryEvaluationException e) {
			e.printStackTrace();
		} catch (BadConfigurationException e) {
			e.printStackTrace();
		} catch (CODAComponentNotSetException e) {
			e.printStackTrace();
		} finally {
			try {
				if (codaCore != null)
					codaCore.stopAndClose();
			} catch (ModelUpdateException e) {
				e.printStackTrace();
			}
			long end = System.currentTimeMillis();
			String prettyTime = "Program terminated after " + completeExec.printPrettyTime(start, end);
			String numAddedTriplesString = "Program added " + completeExec.printPrettyNumber(numAddedTriples) + " RDF triples";
			logger.info(prettyTime);
			logger.info(numAddedTriplesString);
		}

	}

	public List<ImdbDBStruct> exexuteQuery() throws GenericTestException {
		List<ImdbDBStruct> imdbDBStructList = new ArrayList<ImdbDBStruct>();
		try {
			List<String> uriToAddList = null;
			if (checkuriToAdd) {
				uriToAddList = new ArrayList<String>();
				for (int i = 0; i < uriToAddArray.length; ++i)
					uriToAddList.add(uriToAddArray[i]);
			}
			Class.forName("com.mysql.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1/collezioni", "film", "film");
			// Connection con = DriverManager.getConnection("jdbc:mysql://192.168.0.5/collezioni", "test",
			// "test");
			Statement st = con.createStatement();
			ResultSet rs = st.executeQuery("SELECT SitoIMDB, Voto, Varie, NumDVD FROM listadvd ORDER BY id");
			while (rs.next()) {
				String sitoIMDBFromDB = rs.getString(1);
				int voto = rs.getInt(2);
				String varie = rs.getString(3);
				int numDVD = rs.getInt(4);
				if (checkuriToAdd) {
					if (!uriToAddList.contains(sitoIMDBFromDB))
						continue;
				}
				imdbDBStructList.add(new ImdbDBStruct(sitoIMDBFromDB, voto, varie, numDVD));
			}
			con.close();
		} catch (ClassNotFoundException e) {
			throw new GenericTestException(e);
		} catch (SQLException e) {
			throw new GenericTestException(e);
		}

		// imdbDBStructList.add(new ImdbDBStruct("http://www.imdb.com/title/tt0118799/", 5, "", 1)); // La
		// Vita è Bella
		// imdbDBStructList.add(new ImdbDBStruct("http://www.imdb.com/title/tt1504320/", 5, "", 1)); // The
		// King's Speech
		// imdbDBStructList.add(new ImdbDBStruct("http://www.imdb.com/title/tt0887912/", 5, "", 1)); // The
		// Hurt Locker
		// imdbDBStructList.add(new ImdbDBStruct("http://www.imdb.com/title/tt1010048/", 5, "", 1)); // The
		// Millionaire

		return imdbDBStructList;
	}

	public List<ImdbDBStruct> parseImdbFile() throws GenericTestException {
		List<ImdbDBStruct> imdbDBStructList = new ArrayList<ImdbDBStruct>();
		try {

			File file = new File(imdbListFilePath);
			BufferedReader bf = new BufferedReader(new FileReader(file));
			String line;
			while ((line = bf.readLine()) != null) {
				if (!line.startsWith("http"))
					continue;
				imdbDBStructList.add(new ImdbDBStruct(line, 3, "", 1));
			}
		} catch (FileNotFoundException e) {
			throw new GenericTestException(e);
		} catch (IOException e) {
			throw new GenericTestException(e);
		}
		return imdbDBStructList;
	}

	public List<String> getfileHtmlList() {
		List<String> fileHtmlList = new ArrayList<String>();
		File dir = new File(inputFiles);
		File fileArray[] = dir.listFiles();
		for (int i = 0; i < fileArray.length; ++i) {
			fileHtmlList.add(fileArray[i].getAbsolutePath());
		}
		return fileHtmlList;
	}

	public String installPear(String pearPathString, String installedPearString) throws IOException {
		File pearFile = new File(pearPathString);
		File installDir = new File(installedPearString);
		if (installDir.exists()) {
			this.deleteDirectory(installDir);
		}
		PackageBrowser instPear = PackageInstaller.installPackage(installDir, pearFile, true);
		return instPear.getComponentPearDescPath();
	}

	private boolean deleteDirectory(File path) {
		if (path.exists()) {
			File[] files = path.listFiles();
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					deleteDirectory(files[i]);
				} else {
					files[i].delete();
				}
			}
		}
		return (path.delete());
	}

	private String getTextToBeAnnotated(String htmlFilePath) throws IOException {
		// read the input file containig the test to be analized
		HttpURLConnection httpcon = null;
		StringBuilder contents = new StringBuilder();
		try {
			logger.debug("requesting imdb page");
			URL url = new URL(htmlFilePath);
			httpcon = (HttpURLConnection) url.openConnection();
			httpcon.setRequestMethod("GET");
			httpcon.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");

			httpcon.setDoOutput(true);
			httpcon.setConnectTimeout(10 * 1000);
			httpcon.setReadTimeout(10 * 1000);
			httpcon.connect();

			InputStreamReader inputStreamReader = new InputStreamReader(httpcon.getInputStream());
			BufferedReader br = new BufferedReader(inputStreamReader);

			// contents = new StringBuilder();
			String line;

			while ((line = br.readLine()) != null) {
				contents.append(line);
				contents.append(System.getProperty("line.separator"));
			}
		} catch (MalformedURLException e) {
			contents.delete(0, contents.length());
			contents.append("");
			logger.debug("MalformedURLException with: " + htmlFilePath);
			// e.printStackTrace();
		} catch (ProtocolException e) {
			contents.delete(0, contents.length());
			contents.append("");
			logger.debug("ProtocolException with: " + htmlFilePath);
			// e.printStackTrace();
		} catch (IOException e) {
			contents.delete(0, contents.length());
			contents.append("");
			logger.debug("IOException with: " + htmlFilePath);
			// e.printStackTrace();
		} finally {
			// close the connection, set all objects to null
			httpcon.disconnect();
			httpcon.setRequestProperty("Connection", "close");
		}
		logger.debug("imdb page obtained");
		if (contents.toString().compareTo("") == 0) {
			logger.debug("the imdb page " + htmlFilePath + " content is null");
			return "";
		}
		return contents.toString();
	}

	private String getTextToBeAnnotatedFromFile(String fileHtmlPath) {
		StringBuilder contents = new StringBuilder();
		try {
			File file = new File(fileHtmlPath);
			FileInputStream fileInputStream;
			fileInputStream = new FileInputStream(file);
			InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
			BufferedReader br = new BufferedReader(inputStreamReader);
			String line;

			while ((line = br.readLine()) != null) {
				contents.append(line);
				contents.append(System.getProperty("line.separator"));
			}
		} catch (FileNotFoundException e) {
			logger.debug("FileNotFoundException with: " + fileHtmlPath);
		} catch (IOException e) {
			logger.debug("IOException with: " + fileHtmlPath);
		}
		return contents.toString();

	}

	private AnalysisEngine createAnalysisEngine(String descrPathString)
			throws ResourceInitializationException, InvalidXMLException, IOException {
		AnalysisEngine ae;
		// AnalysisEngineDescription aeDesc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription(
		// new XMLInputSource(descrPathString));
		// ae = UIMAFramework.produceAnalysisEngine(aeDesc);
		// ae.setConfigParameterValue("Encoding", "UTF-8");
		ResourceSpecifier specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(
				new XMLInputSource(descrPathString));
		ae = UIMAFramework.produceAnalysisEngine(specifier);
		return ae;
	}

	private JCas createJCas(AnalysisEngine ae) throws ResourceInitializationException {
		JCas jcas = ae.newJCas();
		return jcas;
	}

	private void analyzeNewText(AnalysisEngine ae, JCas jcas, String textToBeAnnotatate)
			throws AnalysisEngineProcessException {
		jcas.reset();
		jcas.setDocumentText(textToBeAnnotatate);
		ae.process(jcas);
	}

	/*
	 * private JCas analyzeText(String descrPathString, String textToBeAnnotatate) throws IOException,
	 * ResourceInitializationException, AnalysisEngineProcessException, InvalidXMLException { // pass the txt
	 * read to the AE (which is an AAE). To do this read the AAE descriptor and then execute // the AAE //
	 * XMLInputSource in; ResourceSpecifier specifier; AnalysisEngine ae; JCas annotCas;
	 * 
	 * // in = new XMLInputSource(aggregateAEFilePath); // in = new XMLInputSource(descrPathString); //
	 * specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(in); // specifier =
	 * UIMAFramework.getXMLParser().parseResourceSpecifier(new // XMLInputSource(descrPathString));
	 * 
	 * AnalysisEngineDescription aeDesc = UIMAFramework.getXMLParser().parseAnalysisEngineDescription( new
	 * XMLInputSource(descrPathString)); ae = UIMAFramework.produceAnalysisEngine(aeDesc);
	 * 
	 * // ae = UIMAFramework.produceAnalysisEngine(specifier); ae.setConfigParameterValue("Encoding",
	 * "UTF-8"); annotCas = ae.newJCas(); annotCas.setDocumentText(textToBeAnnotatate); ae.process(annotCas);
	 * return annotCas; }
	 */

	private OWLModel initializeOWLModel() throws ModelUpdateException, FileNotFoundException, IOException,
			ModelAccessException, UnsupportedRDFFormatException, ClassNotFoundException,
			ModelCreationException, InstantiationException, IllegalAccessException,
			UnsupportedModelConfigurationException, UnloadableModelConfigurationException,
			BadConfigurationException {

		ARTModelFactorySesame2Impl factImpl = new ARTModelFactorySesame2Impl();
		OWLArtModelFactory<Sesame2ModelConfiguration> fact = OWLArtModelFactory.createModelFactory(factImpl);
		Sesame2ModelConfiguration modelConf = factImpl
				.createModelConfigurationObject(Sesame2PersistentInMemoryModelConfiguration.class);
		if (!useResoner) {
			modelConf.directTypeInference = false;
			modelConf.rdfsInference = false;
		}

		OWLModel owlModel = fact.loadOWLModel(baseUri, repositoryDirPath, modelConf);

		owlModel.setBaseURI(baseUri);
		owlModel.setDefaultNamespace(baseUri + "#");
		// owlModel.clearRDF();
		owlModel.addRDF(new File(rdfInputFilePath), importedUri, RDFFormat.RDFXML, NodeFilters.MAINGRAPH);

		ArrayList<String> importedOntologiesList = new ArrayList<String>();
		if(recursiveOntologyImport)
			recursiveImport(owlModel, importedOntologiesList);

		return owlModel;
	}

	private void recursiveImport(OWLModel owlModel, ArrayList<String> importedOntologiesList)
			throws ModelAccessException, FileNotFoundException, MalformedURLException, IOException,
			ModelUpdateException, UnsupportedRDFFormatException {
		ARTURIResourceIterator artUriIter = owlModel.listOntologyImports(NodeFilters.ANY, NodeFilters.ANY);
		while (artUriIter.hasNext()) {
			ARTURIResource artUriRes = artUriIter.next();
			String uriString = artUriRes.getURI();
			if (!importedOntologiesList.contains(uriString)) {
				importedOntologiesList.add(uriString);
				System.out.println("importing ontology: " + uriString);
				owlModel.addRDF(new URL(artUriRes.getURI()), importedUri, RDFFormat.RDFXML,
						NodeFilters.MAINGRAPH);
				recursiveImport(owlModel, importedOntologiesList);
			}
		}
	};

	private CODACore initializeCODACore(JCas annotCas, OWLModel owlModel)
			throws FelixInitializationException, PRParserException {
		File oSGiDir = new File(oSGiDirPath);
		CODACore codaCore = new CODACore();
		codaCore.initialize(annotCas, oSGiDir, dirComponentsPath, false, prFilePath, owlModel, prevDec);
		return codaCore;
	}

	private void setMap(CODACore codaCore) {
		prdMap = codaCore.getProjectionRulesDeciderMap();
		irMap = codaCore.getIdentityResolverMap();
		rssMap = codaCore.getResourcesSmartSuggesterMap();
		tssMap = codaCore.getTriplesSmartSuggesterMap();
	}

	private void setSelectedModule(CODACore codaCore) {
		// Choose the 3 components from the 3 lists, at the moment the first of the lists which are not null
		// are choosen
		String key;
		if (prdMap.isEmpty() == false) {
			key = prdMap.keySet().iterator().next();
			ProjectionRulesDeciderInterface pda = prdMap.get(key);
			codaCore.setProjectionRulesDecider(pda);
		}
		if (irMap.isEmpty() == false) {
			key = irMap.keySet().iterator().next();
			IdentityResolverInterface ida = irMap.get(key);
			codaCore.setIdentityResolver(ida);
		}
		if (rssMap.isEmpty() == false) {
			key = rssMap.keySet().iterator().next();
			ResourcesSmartSuggesterInterface rss = rssMap.get(key);
			codaCore.setResourcesSmartSuggester(rss);
		}
		if (tssMap.isEmpty() == false) {
			key = tssMap.keySet().iterator().next();
			TriplesSmartSuggesterInterface tss = tssMap.get(key);
			codaCore.setTriplesSmartSuggester(tss);
		}
	}

	private long processUIMAAnnotation(CODACore codaCore, OWLModel owlModel) throws ModelUpdateException,
			UnsupportedQueryLanguageException, ModelAccessException, MalformedQueryException,
			QueryEvaluationException, CODAComponentNotSetException {
		long numAddedTriples = 0;
		SuggOntologyCoda suggOntCoda;
		// PrevAnnProjectedList prevAnnProjList = new PrevAnnProjectedList(null);
		while (codaCore.isAnotherAnnotationPrsent()) {
			logger.debug("\n\n");

			suggOntCoda = codaCore.processNextAnnotation();
			logger.debug(
			// suggOntCoda.getAnnotation().getCoveredText() +
					" type: " + suggOntCoda.getAnnotation().getType().toString() + "\t"
							+ suggOntCoda.getAnnotation().getBegin() + " -> "
							+ suggOntCoda.getAnnotation().getEnd());

			SelectedProjectionRules selProjRules = suggOntCoda.getSelProjRules();
			BindLabelToExistingARTURIResource bindLabels = suggOntCoda.getBindLabels();
			ResourcesSmartSuggesterStruct smartSuggs = suggOntCoda.getResSmartSuggestions();
			CodaFinalSuggestions codaSuggs = suggOntCoda.getCodaFinalSuggs();

			logger.debug("%%%Selected Projection Rule:");
			List<ProjectionRule> projRulesList = selProjRules.getProjRuleList();
			for (ProjectionRule projRule : projRulesList) {
				logger.debug("\ttype = " + projRule.getUIMAType() + "\tid: " + projRule.getId());

				logger.debug("%%%Bind Labels:");
				Map<PlaceholderStruct, Map<String, ARTURIResource>> bindMap = bindLabels
						.getPlaceholderToARTURIResMap();
				Iterator<PlaceholderStruct> bindNodeIter = bindMap.keySet().iterator();
				while (bindNodeIter.hasNext()) {
					PlaceholderStruct node = bindNodeIter.next();
					Map<String, ARTURIResource> artUriResMap = bindMap.get(node);
					logger.debug("\t" + node.getName());
					for (ARTURIResource artUriRes : artUriResMap.values())
						logger.debug("\t\t" + artUriRes.getURI());
				}

				logger.debug("%%%Smart Suggestion:");
				Map<PlaceholderStruct, Map<String, ARTURIResource>> smarSugMap = smartSuggs
						.getPlaceholderToARTURIResMap();
				Iterator<PlaceholderStruct> smartSuggIter = smarSugMap.keySet().iterator();
				while (smartSuggIter.hasNext()) {
					PlaceholderStruct node = smartSuggIter.next();
					Map<String, ARTURIResource> artUriResMap = smarSugMap.get(node);
					logger.debug("\t" + node.getName());
					for (ARTURIResource artUriRes : artUriResMap.values())
						logger.debug("\t\t" + artUriRes.getURI());
				}

				logger.debug("%%%Suggested Triple:");
				List<ARTTriple> artTripleList = codaSuggs.getTriplesList();
				for (ARTTriple artTriple : artTripleList) {
					logger.debug("\tTriple:");
					ARTURIResource subjUri = artTriple.getSubjectUri();
					logger.debug("\t\t" + subjUri.getURI());
					ARTURIResource predUri = artTriple.getPredicateUri();
					logger.debug("\t\t" + predUri.getURI());
					if (artTriple.isObjARes()) {
						ARTURIResource objUri = artTriple.getObjectUri();
						logger.debug("\t\t" + objUri.getURI() + "\tURI");
					} else {
						ARTLiteral objLit = artTriple.getObjectLiteral();
						logger.debug("\t\t" + objLit.getLabel() + "\tLiteral");
					}
				}
			}
			// add the suggestion and the just added triple to the prevDec
			List<ARTTriple> addedTripleList = new ArrayList<ARTTriple>();
			if (!useAutocommit)
				((TransactionBasedModel) owlModel).setAutoCommit(false);
			for (ARTTriple artTriple : suggOntCoda.getCodaFinalSuggs().getTriplesList()) {
				ARTURIResource subject = artTriple.getSubjectUri();
				ARTURIResource predicate = artTriple.getPredicateUri();
				ARTNode object;
				if (artTriple.isObjARes()) {
					object = artTriple.getObjectUri();
				} else { // artTriple.isObjARes == false
					object = artTriple.getObjectLiteral();
				}
				owlModel.addTriple(subject, predicate, object);
				numAddedTriples++;
				addedTripleList.add(artTriple);
			}
			if (!useAutocommit)
				((TransactionBasedModel) owlModel).commit();
			PreviousDecisionSingleElement prevDecSingleElem = new PreviousDecisionSingleElement(
					addedTripleList, suggOntCoda);
			prevDec.addPrevDecSingleElem(prevDecSingleElem);
		}
		return numAddedTriples;
	}

	private void saveRDF(OWLModel owlModel) throws IOException, ModelAccessException,
			UnsupportedRDFFormatException {
		logger.info("saving rdf to : " + rdfOutputFilePath); // convert to DEBUG
		owlModel.writeRDF(new File(rdfOutputFilePath), RDFFormat.RDFXML, NodeFilters.MAINGRAPH);
	}

	public void clearAllPrevDec() {
		prevDec.clearAllPrevDec();
	}

	public void setNumOfPrevDec(int numPrevDec) {
		prevDec.setMaxPrevDev(numPrevDec);
	}

	public void addOtherInfoToRDF(RDFModel rdfModel, String sitoIMDB, int voto, String varie, int numDVD)
			throws ModelAccessException, ModelUpdateException {
		ARTURIResource predType = rdfModel.createURIResource("http://art.uniroma2.it/imdb#hasSite");
		ARTURIResource typeOfLiteralArtRes = rdfModel
				.createURIResource("http://www.w3.org/2001/XMLSchema#string");
		ARTNode artNodeSiteIMDB = rdfModel.createLiteral(sitoIMDB, typeOfLiteralArtRes);
		ARTStatementIterator artIter = rdfModel.listStatements(NodeFilters.ANY, predType, artNodeSiteIMDB,
				false, NodeFilters.ANY);

		if (!artIter.hasNext()) {
			logger.info("ERROR, no value for site : " + sitoIMDB);
			return;
		}
		ARTStatement artStatement = artIter.next();
		ARTResource subj = artStatement.getSubject();

		// add voto
		predType = rdfModel.createURIResource("http://art.uniroma2.it/imdb#myScore");
		typeOfLiteralArtRes = rdfModel.createURIResource("http://www.w3.org/2001/XMLSchema#integer");
		ARTLiteral artLiteralMyScore = rdfModel.createLiteral(voto + "", typeOfLiteralArtRes);
		rdfModel.addTriple(subj, predType, artLiteralMyScore);

		// add varie
		predType = rdfModel.createURIResource("http://art.uniroma2.it/imdb#varie");
		typeOfLiteralArtRes = rdfModel.createURIResource("http://www.w3.org/2001/XMLSchema#string");
		ARTLiteral artLiteralVarie = rdfModel.createLiteral(varie, typeOfLiteralArtRes);
		rdfModel.addTriple(subj, predType, artLiteralVarie);

		// add numDVD
		predType = rdfModel.createURIResource("http://art.uniroma2.it/imdb#numDVD");
		typeOfLiteralArtRes = rdfModel.createURIResource("http://www.w3.org/2001/XMLSchema#integer");
		ARTLiteral artLiteralnumDVD = rdfModel.createLiteral(numDVD + "", typeOfLiteralArtRes);
		rdfModel.addTriple(subj, predType, artLiteralnumDVD);

	}

	public String printPrettyTime(long start, long end) {
		long secTotal = (end - start) / 1000;
		long sec = secTotal % 60;
		long minTotal = secTotal / 60;
		long min = minTotal % 60;
		long hourTotal = minTotal / 60;

		String prettyTime = "";
		if (hourTotal < 10)
			prettyTime += "0";
		prettyTime += hourTotal + ":";
		if (min < 10)
			prettyTime += "0";
		prettyTime += min + ":";
		if (sec < 10)
			prettyTime += "0";
		prettyTime += sec;

		return prettyTime;
	}
	
	public String printPrettyNumber(long number){
		String prittyTime="";
		long temp=number;
		long remainder = 0;
		while(temp/1000 != 0) {
			remainder = temp % 1000;
			prittyTime = "."+remainder+prittyTime;
			temp /= 1000;
		}
		remainder = temp % 1000;
		prittyTime = +remainder+prittyTime;
		return prittyTime;
	}

}
